﻿using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using SQLPXBase.Factory.Keys;

namespace SQLPXBase.Factory
{
    public class Utils
    {
        public static void InitializeLazyKeysAndExtensionKeys<PX>(object model, ModelFactory<PX> factory)
            where PX : Interfaces.ISQLProxyBase, new()
        {
            // Inizializza le LazyKey
            foreach (PropertyInfo p in model.GetType().GetProperties()
                .Where(p =>
                    (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(LazyKey<,>))
                    || typeof(BaseLazyKey<PX>).IsAssignableFrom(p.PropertyType)))
            {
                ConstructorInfo info = p.PropertyType.GetConstructor(new[] { factory.GetType() });
                if (info != null)
                {
                    if (p.CanWrite)
                        p.SetValue(model,
                            info.Invoke(new object[] {factory}),
                            null);
                    else
                        throw new Exception(
                            string.Format(
                                "LazyKey cannot be initialized due to inaccessibility: {0} on model of type: {1}",
                                p.Name, model.GetType().FullName));
                }
            }

            // Collega le ExtensionKey
            foreach (PropertyInfo p in model.GetType().GetProperties()
                .Where(p =>
                    (p.PropertyType.IsGenericType &&
                     p.PropertyType.GetGenericTypeDefinition() == typeof(ExtensionKey<,>))
                    || typeof(BaseExtensionKey<PX>).IsAssignableFrom(p.PropertyType)))
            {
                ConstructorInfo info = p.PropertyType.GetConstructor(new[] { model.GetType() });
                if (info != null)
                {
                    if (p.CanWrite)
                        p.SetValue(model,
                            info.Invoke(new object[] {model}),
                            null);
                    else
                        throw new Exception(
                            string.Format(
                                "LazyKey cannot be initialized due to inaccessibility: {0} on model of type: {1}",
                                p.Name, model.GetType().FullName));
                }
                else
                {
                    throw new Exception(string.Format("Cannot instantiate ExtensionKey with instance of type: {0}",
                        model.GetType().FullName));
                }
            }
        }

        public static Type GetDeclaredType<TSelf>(TSelf self)
        {
            return typeof(TSelf);
        }

        public static string SqlValueToString(object o)
        {
            if (o == null) return "";

            return string.Format("'{0}'", o);
        }

        public static object[] ConvertFromDatabaseValues(params object[] values)
        {
            if (values == null) return null;

            ArrayList tmp = new ArrayList();
            foreach (object v in values)
                tmp.Add(v is DBNull ? null : v);
            return tmp.ToArray();
        }
    }

    public static class DBSafe
    {
        public static object[] SafeFromDb(this object[] values)
        {
            return Utils.ConvertFromDatabaseValues(values);
        }
    }


}
